#!/usr/bin/env python3
#coding: utf-8
import smtplib, sys, os, re, urllib, urllib2, socket, webbrowser
import random, time, json
import cookielib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.Header import Header

sender = 'fromname@126.com'
receiver = 'toname@geo-k.cn'
subject = 'python email test'
smtpserver = 'smtp.126.com'
username = 'name'
password = 'password'
savepath = './img'


TIMEOUT = 20                                        # 超时
VER_PATH = './verify'                               # 验证码目录
VER_IMG_URL = 'http://ucenter.51cto.com/verify.php' # 验证码图片 ?rnum=random(10000)
REG_URL = 'http://ucenter.51cto.com/reg_01.php'     # 注册地址
MAIL_MX = '@mailinator.com'
API_KEY = '3566fc4f9b804f398d340ecc75e6a9f7'
USER_FILE = './users.txt'

socket.setdefaulttimeout(TIMEOUT)
#reload(sys)
#sys.setdefaultencoding('utf-8')


# 读取注册码
# 提交表单
# 搜集用户名
# 随机用户名
# 收取激活邮件
# 激活邮件
# 保存cookie
# 重发激活邮件

class FastREG:
    
    _opener = None
    def __init__(self):
        # 成员变量
        self._opener = None
        
        # 初始化
        self.CreateNew()
        
    
    def CreateNew(self):
        # 生成新的cookie
        cookie = cookielib.CookieJar()
        handle = urllib2.HTTPCookieProcessor(cookie)
        self._opener = urllib2.build_opener(handle)
        pass

    def GetVerIMG(self):
        # 读取验证码
        savename = os.path.join(VER_PATH, 'verify.jpg')
        data = self._opener.open(VER_IMG_URL).read()
        with open(savename, 'wb') as jpg:
            jpg.write(data)
        pass

    def ShowVerIMG(self):
        # 显示验证码
        savename = os.path.join(VER_PATH, 'verify.jpg')
        webbrowser.open(savename, new=0, autoraise=True)
        pass

    def PostForm(self, verify):
        # 提交表单
        # req = urllib2.Request(url, post_data, headers)
        # content = opener.open(req)
        # headers ={"User-agent":"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1"}
        username = self.NewUser()
        password = username

        data = {}
        data['checkpwd'] = '1'
        data['checkname'] = '1'
        data['checkemail'] = '0'
        data['step'] = '1'
        data['username'] = username
        data['email'] = username + MAIL_MX
        data['emailexist'] = '0'
        data['usernameexist'] = '0'
        data['yanzhengexsit'] = '0'
        data['userpwd'] = password
        data['password2'] = password
        data['gzly'] = '01'
        data['sshy'] = '01'
        data['zw'] = '03'
        data['companysize'] = '1'
        data['province'] = '11'
        data['city'] = '1101'
        data['code'] = verify
        data['agree'] = '1'
        data['x'] = '25'
        data['y'] = 15
        post_data = urllib.urlencode(data)              # 将post消息化成可以让服务器编码的方式
        headers = {"User-agent" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1"}

        req = urllib2.Request(REG_URL, post_data, headers)
        content = self._opener.open(req)
        html = content.read()

        # 判断是否成功 查找字符串 alert 如果字符串出现在前20个字符说明不成功
        index = html.index('alert')
        if (index < 20) : return None, None, None
        else: return username, password, username + MAIL_MX
        

    def GetMail(self, boxname):
        # 读取激活邮件
        inbox = Inbox(API_KEY)
        for index in range(5):
            try:
                inbox.get(boxname)
                if len(inbox.messages) > 0:                
                    mail = inbox.messages[0]
                    mail.get_message()
                    return mail.body
                    
                print 'trying %d ...' % (index + 1)
                time.sleep(2)
            except Exception as ex:
                print 'Error ..'
                continue
        return None

    def GetAttivationURL(self, html):
        # 解析激活URL
        # target=_blank>URL</a>
        match_url = re.search(r'target=_blank>(?P<url>.*?)</a>', html)
        url = match_url.group('url')
        return url

    def ResetMail():
        # 重新发送激活邮件
        pass

    def Activation(self, url):
        # 激活用户
        html = self._opener.open(url).read()
        index = html.decode('utf8').index(u'\u6ce8\u518c\u6210\u529f</title>')
        return index > 0

    def NewUser(self):
        # 随机生成一个用户名 不能以数字开头
        name = 'dodo'
        name += str(hex(int(random.randrange(4096, 65535)))[2:])
        name += str(hex(int(time.time()))[8:])
        return name

            

def Init():
    # 初始化
    if os.path.exists(VER_PATH) == False:
        os.mkdir(VER_PATH)



######################################################################
######################################################################
class InvalidToken(Exception):
    pass

class MissingToken(Exception):
    pass

class MessageNotFound(Exception):
    pass

class Message(object):
    """Message Object for Mailinator Email API
    """
    _baseURL = 'http://api.mailinator.com/api/email'

    def __init__(self, token, data):
        self.token = token
        self.id = data['id']
        self.subject = data['subject']
        self.time = data['time']
        self.to = data['to']
        self.seconds_ago = data['seconds_ago']
        self.fromfull = data['fromfull']
        self.been_read = data['been_read']
        self.fromshort = data['from']
        self.ip = data['ip']
        self.headers = {}
        self.body = ""

    def get_message(self):
        query_string = {'token': self.token, 'msgid': self.id}
        url = self._baseURL + "?" + urllib.urlencode(query_string)
        request = urllib.urlopen(url)
        if request.getcode() == 404:
            raise MessageNotFound
        response = request.read()
        data = json.loads(clean_response(response), strict=False)
        self.headers = data['data']['headers']
        self.body = "".join([part['body'] for part in data['data']['parts']])


class Inbox(object):
    """Inbox Object for retrieving an inbox

    Args:
        token: An api token, from http://www.mailinator.com/settings.jsp
    Methods:
        get:
            Args:
                mailbox: optional argument for the name of an inbox
    Returns:

    Raises:
        InvalidToken: When the api token is invalid
        MissingToken: When run without a token

    """
    _baseURL = "http://api.mailinator.com/api/inbox"

    def __init__(self, token):
        self.token = token
        self.messages = []

    def get(self, mailbox=None, private_domain=False):
        """Retrieves email from inbox"""
        if not self.token:
            raise MissingToken
        query_string = {'token': self.token}
        if mailbox:
            query_string.update({'to': mailbox})
        if private_domain:
            query_string.update({'private_domain': json.dumps(private_domain)})
        url = self._baseURL + '?' + urllib.urlencode(query_string)
        request = urllib.urlopen(url)
        if request.getcode() == 400:
            raise InvalidToken
        response = request.read()
        return self._parse(response)

    def count(self):
        """returns the number of emails in inbox"""
        return len(self.messages)

    def view_subjects(self):
        """returns a list of messages subjects"""
        return [message.subject for message in self.messages]

    def view_message_ids(self):
        """returns a list of message ids"""
        return [message.id for message in self.messages]

    def get_message_by_subject(self, subject):
        """returns a message object with a subject line"""
        messages = [message for message in self.messages if message.subject.lower() == subject.lower()]
        if len(messages) == 0:
            return None
        elif len(messages) == 1:
            return messages[0]
        else:
            return messages

    def get_message_by_id(self, msgid):
        """returns a message object by id"""
        messages = [message for message in self.messages if message.id == msgid]
        if len(messages) == 0:
            return None
        elif len(messages) == 1:
            return messages[0]

    def filter(self, field, value):
        """returns a filtered list of messages by where message.field = value"""
        return [message for message in self.messages if getattr(message, field) == value]

    def _parse(self, data):
        self.messages = []
        parsed = json.loads(clean_response(data), strict=False)
        for message in parsed['messages']:
            email = Message(self.token, message)
            self.messages.append(email)
        return self.messages


def clean_response(response):
    return response.replace('\r\n', '').decode('utf-8', 'ignore')


######################################################################
######################################################################





if __name__ == '__main__':
    # main
    print sys.getdefaultencoding()
    Init()


    # 循环工作
    while True:
        fastREG = FastREG()

        fastREG.GetVerIMG()                     # 下载验证码
        #fastREG.ShowVerIMG()                    # 显示验证码
        
        # 等待用户输入
        verify = raw_input(u'\u9a8c\u8bc1\u7801:')
        if verify.strip() == '' : break

        # 注册 如果成功返回用户名
        username, password, email = fastREG.PostForm(verify)

        if username == None:
            print u'\u6ce8\u518c\u5931\u8d25'
            continue
        print 'username: {0}\r\npassword: {1}\r\nemail: {2}'.format(username, password, email)

        content = fastREG.GetMail(username)
        if content == None:
            print u'\u672a\u6536\u5230\u6fc0\u6d3b\u90ae\u4ef6'
            continue
        print 'receive mail ok'

        # 该死的编码要解码真难受 #isinstance(mail.body, unicode)
        message = ''
        for c in content:
            message += '%{0}'.format(hex(ord(c))[2:])
        message = urllib.unquote(message)

        # 解析出激活邮件的URL
        url = fastREG.GetAttivationURL(message)
        if (url == None or url == ''):
            print u'\u672a\u80fd\u83b7\u53d6\u6fc0\u6d3b\u5730\u5740'
            continue
        print 'url: {0}'.format(url)

        # 激活账户
        success = fastREG.Activation(url)
        if (success == False):
            print u'\u6fc0\u6d3b\u5931\u8d25'
            continue
        print 'user acctivation ok'

        # 保存用户
        userfile = open(USER_FILE, 'a')
        userfile.write('%s\t%s\t%s\n' % (username, password, email))
        userfile.close()
            
        print '=========================================='

        













    
